﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MMITWeb.Infrastructure.Abstract;
using MMITWeb.Models;
using MMITDomain.Abstract;
using MMITDomain.Entities;
using System.Web.Security;
using MMITCore.Abstract;
using MMITCore.Logging;

namespace MMITWeb.Controllers
{
    public class UserAccountController : Controller
    {
        IAuthProvider authProvider;
        ICountryRepository countryRepository;
        IIdentificationTypeRepository identificationTypeRepository;
        ICustomerRepository customerRepository;
        ILogger<SynkronLogger> _logger;

        public UserAccountController(IAuthProvider auth, ICountryRepository countryRepository, 
            IIdentificationTypeRepository identificationTypeRepository,ILogger<SynkronLogger> logger,
            ICustomerRepository customerRepository)
        {
            authProvider = auth;
            this.countryRepository = countryRepository;
            this.identificationTypeRepository = identificationTypeRepository;
            this.customerRepository = customerRepository;
            _logger = logger;
        }
        
        public ViewResult LogOn()
        {
            return View();
        }

        [HttpPost]
        public ActionResult LogOn(LogOnViewModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (authProvider.Authenticate(model.Username, model.Password))
                {
                    //Log Sucessfull Login
                    _logger.WriteInformation(2000000, () => "User Login Successful",
                        new Dictionary<string, object> { { string.Format("Logon User: {0} IPADRR: {1}", model.Username, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(model) },
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}    
                    });
                    return Redirect(returnUrl ?? Url.Action("Index", "Home"));
                }
                else
                {
                    ModelState.AddModelError("", "Incorrect username or password");
                    _logger.WriteWarning(2000001, () => "User Login Failure",
                        new Dictionary<string, object> { { string.Format("Logon User: {0} IPADRR: {1}", model.Username, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(model) } ,
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}                        
                        });
                    return View();
                }
            }
            else
            {
                return View();
            }
        }

        public ActionResult Register()
        {
            //Get countries...
            var countries = countryRepository.Countries.ToList().Select(x => new Telerik.Web.Mvc.UI.DropDownItem
                                                                {
                                                                    Text = x.Name,
                                                                    Value = x.Id.ToString()
                                                                });
            

            //Get Identification Types...
            var identifications = from idents in identificationTypeRepository.IdentificationTypes.ToList()
                                  select new Telerik.Web.Mvc.UI.DropDownItem
                                  {
                                      Text = idents.Name,
                                      Value = idents.Id.ToString()
                                  };
            RegisterViewModel model = new RegisterViewModel() {Countries = countries, IdentificationTypes = identifications };

            return View(model);
        }

        [HttpPost]
        public ActionResult Register(RegisterViewModel model,int CountryId, int IdentificationTypeId)
        {
            string strErrorCode;

            //Repopulate drop downs....
            model.Countries = countryRepository.Countries.ToList().Select(x => new Telerik.Web.Mvc.UI.DropDownItem
            {
                Text = x.Name,
                Value = x.Id.ToString()
            });

            model.IdentificationTypes = from idents in identificationTypeRepository.IdentificationTypes.ToList()
                                        select new Telerik.Web.Mvc.UI.DropDownItem
                                        {
                                            Text = idents.Name,
                                            Value = idents.Id.ToString()
                                        };
            
            if (ModelState.IsValid)
            {
                //Register User
                if (authProvider.Register(model.UserName, model.Password, model.Email, model.Firstname,
                    model.Middlename, model.Lastname, string.Format("{0}{1}",model.CountryCode,model.Mobile), model.Sex,CountryId, IdentificationTypeId, model.IdentificationNumber,
                    out strErrorCode))
                {
                    //Log Succesful User Registration..
                    _logger.WriteInformation(20000003, () => "User Registration Successful",
                        new Dictionary<string, object> { { string.Format("Registered User: {0} IPADRR: {1}", model.UserName, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(model) },
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}                        
                        });
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    //Failure Registration..
                    _logger.WriteWarning(2000004, () => "User Registration Failure", new Exception(strErrorCode),
                       new Dictionary<string, object> { { string.Format("User Info: {0} IPADRR: {1}", model.UserName, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(model) }, 
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}                       
                    });
                    ModelState.AddModelError("", strErrorCode);
                }
                
            }
            // If we got this far, something failed, redisplay form
            return View(model);
        }

        public ActionResult LogOff()
        {
            //User LogOff
            authProvider.LogOff();
            _logger.WriteInformation(2000005, () => "User LogOff",
                       new Dictionary<string, object> { { string.Format("Logon User: {0} IPADRR: {1}", HttpContext.User.Identity.Name, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(HttpContext.User)},
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}                       
                   });
            return RedirectToAction("LogOn", "UserAccount");
        }

        [Authorize]
        public ActionResult ChangePassword()
        {
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordViewModel model)
        {
            if (ModelState.IsValid)
            {
                if (authProvider.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                {
                    _logger.WriteInformation(2000006, () => "User Password Change Success",
                        new Dictionary<string, object> { { string.Format("Logon User: {0} IPADRR: {1}", User.Identity.Name, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(User) },
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}                        
                   }); 
                   return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    _logger.WriteInformation(2000007, () => "User Password Change Failure",
                        new Dictionary<string, object> { { string.Format("Logon User: {0} IPADRR: {1}", User.Identity.Name, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(User) },
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}                        
                    }); 
                    return PartialView("_CoreResponsePartial", new List<string>(){"Error Updating Password"});
                }

            }

            var errors = from t in ModelState.Values.ToList()
                         where t.Errors.Count > 0
                         select t.Errors;
                         
            return PartialView("_ResponsePartial", errors);
        }

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

        [Authorize]
        public ActionResult UpdateUserProfile()
        {
            //Get current logged in user details...
            var objCustomer = (from customer in customerRepository.Customers
                               where customer.Username == User.Identity.Name
                              select customer).SingleOrDefault<Customer>();

            //Get countries...
            var countries = countryRepository.Countries.ToList().Select(x => new Telerik.Web.Mvc.UI.DropDownItem
            {
                Text = x.Name,
                Value = x.Id.ToString(),
                Selected = (x.Id == objCustomer.CountryId)
            });

            //Get Identification Types...
            var identifications = from idents in identificationTypeRepository.IdentificationTypes.ToList()
                                  select new Telerik.Web.Mvc.UI.DropDownItem
                                  {
                                      Text = idents.Name,
                                      Value = idents.Id.ToString(),
                                      Selected = (idents.Id == objCustomer.IdentificationTypeId)
                                  };

            //Instantiate the User Profile View Model
            UserProfileViewModel model = new UserProfileViewModel()
            {
                FirstName = objCustomer.Firstname,
                Middlename = objCustomer.Middlename,
                Lastname = objCustomer.Lastname,
                Sex = objCustomer.Sex == "M"? "Male" : "Female",
                Mobile = objCustomer.Mobile,
                Username = objCustomer.Username,
                IdentificationNumber = objCustomer.IdentificationNumber,
                Email = authProvider.GetUserEmail(User.Identity.Name),
                Countries = countries,
                IdentificationTypes = identifications
            };
            
            //Pass the view model to the View..
            return View(model);
        }

        [HttpPost]
        public ActionResult UpdateUserProfile(UserProfileViewModel model, int CountryId, int IdentificationTypeId)
        {
            try
            {
                //Get countries...
                var countries = countryRepository.Countries.ToList().Select(x => new Telerik.Web.Mvc.UI.DropDownItem
                {
                    Text = x.Name,
                    Value = x.Id.ToString()
                });

                //Get Identification Types...
                var identifications = from idents in identificationTypeRepository.IdentificationTypes.ToList()
                                      select new Telerik.Web.Mvc.UI.DropDownItem
                                      {
                                          Text = idents.Name,
                                          Value = idents.Id.ToString()
                                      };
                model.Countries = countries;
                model.IdentificationTypes = identifications;
                

                if (ModelState.IsValid)
                {
                    //call authprovider to update user profile...
                    authProvider.UpdateUserEmail(model.Username,model.Email);
                    
                    //update Customer Profile...
                    Customer objCustomer = customerRepository.GetCustomerByUsername(User.Identity.Name);
                    objCustomer.Firstname = model.FirstName;
                    objCustomer.Middlename = model.Middlename;
                    objCustomer.Lastname = model.Lastname;
                    objCustomer.Mobile = model.Mobile;
                    objCustomer.Country = countryRepository.GetCountryById(CountryId);
                    objCustomer.IdentificationNumber = model.IdentificationNumber;
                    
                    //replace the assignment to an instance of the identificationType class..
                    objCustomer.IdentificationTypeId = IdentificationTypeId;

                    customerRepository.SaveCustomer(objCustomer);
                    
                    //User Profile Updated Successful

                    _logger.WriteInformation(2000008, () => "User Profile Updated Successfully",
                        new Dictionary<string, object> { { string.Format("Logon User: {0} IPADRR: {1}", User.Identity.Name, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(User) },
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}                        
                    }); 

                    return PartialView("_CoreResponsePartial", new List<string>(){"Profile Updated Sucessfully.."});
                }
            }
            catch (Exception Ex)
            {
                //Log Errors...
                _logger.WriteError(2000009, () => "User Profile Update Exception",Ex,
                       new Dictionary<string, object> { { string.Format("Logon User: {0} IPADRR: {1}", User.Identity.Name, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(User) },
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}                       
                }); 
                
                return PartialView("_CoreResponsePartial", new List<string>() { "Error Updating Profile.." });
            }

            var errors = from v in ModelState.Values.ToList()
                         where v.Errors.Count > 0
                         select v.Errors;

            return PartialView("_ResponsePartial", errors);
        }

        public ActionResult ForgotPassword()
        {

            return View();
        }

        [HttpPost]
        public ActionResult ForgotPassword(ForgotPasswordViewModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    authProvider.ResetPassword(model.Username, model.Email);

                    _logger.WriteInformation(2000010, () => "User Password Reset Successful",
                           new Dictionary<string, object> { { string.Format("Logon User: {0} IPADRR: {1}", User.Identity.Name, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(User) } }); 

                    return RedirectToAction("PasswordSent");
                }
                catch (Exception Ex)
                {
                    _logger.WriteError(2000011, () => "User Profile Update Exception", Ex,
                      new Dictionary<string, object> { { string.Format("Logon User: {0} IPADRR: {1}", User.Identity.Name, Request.ServerVariables["REMOTE_ADDR"]), _logger.Desc(User) },
                            {string.Format("Action Method : {0}",this.ControllerContext.RouteData.GetRequiredString("action")),_logger.Desc(this.ControllerContext)}                      
                    }); 
                    ModelState.AddModelError("", Ex.Message);
                }
            }
            

            return View();
        }

        public ActionResult PasswordSent()
        {
            return View();
        }

        
        public JsonResult GetCountryCode(int CountryId)
        {
            var p = countryRepository.GetCountryById(CountryId);
            JsonResult jResult = new JsonResult();
            
            if (p != null)
            {
                jResult = Json(new {code = p.DiallingCode != null? p.DiallingCode : string.Empty}, JsonRequestBehavior.AllowGet);
            }

            return jResult;
        }
    }
}
